// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.process.editors;

import java.util.EventObject;

import org.dengues.commons.IDenguesCoreContants;
import org.dengues.core.DenguesCorePlugin;
import org.dengues.core.process.EConnectionType;
import org.dengues.designer.ui.editors.GEFEditorContextMenuProvider;
import org.dengues.designer.ui.editors.GEFEditorFreeformRootEditPart;
import org.dengues.designer.ui.editors.actions.GEFCopyAction;
import org.dengues.designer.ui.editors.actions.GEFDeleteAction;
import org.dengues.designer.ui.editors.actions.GEFPasteAction;
import org.dengues.designer.ui.editors.dnd.GEFEditorDropTargetListener;
import org.dengues.designer.ui.editors.outline.ProcessEditorOutlinePage;
import org.dengues.designer.ui.editors.palette.CompEditorPaletteFactory;
import org.dengues.designer.ui.i18n.Messages;
import org.dengues.designer.ui.process.actions.ConnectionCreateAction;
import org.dengues.designer.ui.process.models.CompProcess;
import org.dengues.designer.ui.process.parts.CompProcessPartFactory;
import org.dengues.designer.ui.properties.DenguesEditorTabbedPropertySheetPage;
import org.dengues.ui.editors.AbstractGenericGEFEditor;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.gef.ContextMenuProvider;
import org.eclipse.gef.SnapToGrid;
import org.eclipse.gef.dnd.TemplateTransferDropTargetListener;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.requests.CreationFactory;
import org.eclipse.gef.requests.SimpleFactory;
import org.eclipse.gef.ui.actions.SelectionAction;
import org.eclipse.gef.ui.parts.ScrollingGraphicalViewer;
import org.eclipse.gef.ui.parts.TreeViewer;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.ui.views.properties.IPropertySheetPage;

/**
 * qzhang class global comment. Detailled comment <br/>
 * 
 * 
 */
public class GEFComponentsEditor extends AbstractGenericGEFEditor {

    private static PaletteRoot root;

    public static final int GRID_SIZE = 32;

    private CompProcess process;

    /**
     * qzhang GEFComponentsEditor constructor comment.
     */
    public GEFComponentsEditor() {
        super();
        process = new CompProcess();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#getPaletteRoot()
     */
    @Override
    protected PaletteRoot getPaletteRoot() {
        if (root == null) {
            root = CompEditorPaletteFactory.create(factory);
        }
        return root;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditor#configureGraphicalViewer()
     */
    @Override
    protected void configureGraphicalViewer() {
        super.configureGraphicalViewer();
        ScrollingGraphicalViewer viewer = (ScrollingGraphicalViewer) getGraphicalViewer();
        GEFEditorFreeformRootEditPart root = new GEFEditorFreeformRootEditPart(getEditorInput());
        viewer.setRootEditPart(root);

        GEFDeleteAction deleteAction = new GEFDeleteAction(this);
        getActionRegistry().registerAction(deleteAction);
        getSelectionActions().add(deleteAction.getId());

        SelectionAction action = new GEFCopyAction(this);
        getActionRegistry().registerAction(action);
        getSelectionActions().add(action.getId());

        action = new GEFPasteAction(this);
        getActionRegistry().registerAction(action);
        getSelectionActions().add(action.getId());

        ConnectionCreateAction createAction = new ConnectionCreateAction(this, EConnectionType.MAIN);
        getActionRegistry().registerAction(createAction);
        getSelectionActions().add(createAction.getId());

        ContextMenuProvider menuProvider = new GEFEditorContextMenuProvider(this, viewer, getActionRegistry());
        viewer.setContextMenu(menuProvider);

        getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_SPACING, new Dimension(GRID_SIZE, GRID_SIZE));
        getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_ENABLED, new Boolean(true));
        // We keep grid visibility and enablement in sync
        getGraphicalViewer().setProperty(SnapToGrid.PROPERTY_GRID_VISIBLE, new Boolean(true));

        getGraphicalViewer().setEditPartFactory(new CompProcessPartFactory());
    }

    private boolean savePreviouslyNeeded;

    @Override
    public void commandStackChanged(EventObject event) {
        if (isDirty()) {
            if (!this.savePreviouslyNeeded) {
                this.savePreviouslyNeeded = true;
                firePropertyChange(IEditorPart.PROP_DIRTY);
            }
        } else {
            savePreviouslyNeeded = false;
            firePropertyChange(IEditorPart.PROP_DIRTY);
        }
        super.commandStackChanged(event);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#initializeGraphicalViewer()
     */
    @Override
    protected void initializeGraphicalViewer() {
        super.initializeGraphicalViewer();
        getGraphicalViewer().setContents(process);
        getGraphicalViewer().addDropTargetListener(createTransferDropTargetListener());
        getGraphicalViewer().addDropTargetListener(new GEFEditorDropTargetListener(this));
    }

    private TransferDropTargetListener createTransferDropTargetListener() {
        return new TemplateTransferDropTargetListener(getGraphicalViewer()) {

            @Override
            protected CreationFactory getFactory(Object template) {
                return new SimpleFactory((Class) template);
            }
        };
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
     */
    @Override
    protected void setInput(IEditorInput input) {
        super.setInput(input);
        if (input instanceof ProcessEditorInput) {
            ProcessEditorInput processEditorInput = ((ProcessEditorInput) input);
            process = processEditorInput.getProcess();
        }
    }

    public String getProcessTitle() {
        return DenguesCorePlugin.getDefault().getDenguesTitle(
                ((ProcessEditorInput) getEditorInput()).getFile().getFullPath().toPortableString().substring(1));
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
     */
    @SuppressWarnings("unchecked")//$NON-NLS-1$
    @Override
    public void doSave(IProgressMonitor monitor) {
        monitor.beginTask(Messages.getString("GEFDatabaseEditor.TaskName"), 100); //$NON-NLS-1$
        monitor.worked(10);
        try {
            ProcessEditorInput processEditorInput = (ProcessEditorInput) getEditorInput();
            processEditorInput.saveEMF(process);
            getCommandStack().markSaveLocation();
            setDirty(false);
            monitor.worked(10);
            processEditorInput.getCodeFile();
        } catch (Exception e) {
            e.printStackTrace();
            monitor.setCanceled(true);
        } finally {
            monitor.done();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
     */
    public String getContributorId() {
        return IDenguesCoreContants.ID_VIEW_PROP;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.gef.ui.parts.GraphicalEditorWithFlyoutPalette#getAdapter(java.lang.Class)
     */
    @Override
    public Object getAdapter(Class type) {
        if (type == IPropertySheetPage.class) {
            return new DenguesEditorTabbedPropertySheetPage(this);
        } else if (type == IContentOutlinePage.class) {
            return new ProcessEditorOutlinePage(new TreeViewer());
        }
        return super.getAdapter(type);
    }

    /**
     * Getter for process.
     * 
     * @return the process
     */
    public CompProcess getProcess() {
        return this.process;
    }

    public IPath getPath() {
        return ((ProcessEditorInput) getEditorInput()).getPath();
    }
}
